/* 
  Copyright (c) SilverLining 2015
  Date:    2016-1-7
  File:    json_node.cpp  
  Description: 

*/

#include "stdafx.h"


using namespace m;
using namespace m::alloc;
using namespace m::error;

#define PATH_SEPARATOR L"/"

namespace m
{
	namespace text
	{
		json_node::json_node()
			: _Name(nullptr),
			_Type(JsonNodeType::JsonNil),
			_Parent(nullptr),
			_Child(nullptr),
			_Sibling(nullptr)
		{
		}

		json_node::~json_node()
		{
			ClearName();
			ClearValue();
			clear(_Parent);
			clear(_Child);
			clear(_Sibling);
		}

		bool json_node::remove()
		{
			if (_Parent)
			{
				ref_storage track1;
				json_node* parent = lock<json_node>(track1, _Parent);
				bool ret = false;
				if (parent)
				{
					json_node* last = nullptr;
					json_node* cur = parent->child();
					while (cur)
					{
						if (cur == this)
						{
							if (last)
							{
								assign(last->_Sibling, cur->_Sibling);
							}
							else // if (parent->_Child == cur)
							{
								assert(parent->_Child == cur);
								if (parent->_Child == cur)
								{
									assign(parent->_Child, cur->_Sibling);
								}
							}

							_Parent = nullptr;
							return true;
						}

						last = cur;
						cur = cur->_Sibling;
					}
				}
			}
			return false;
		}

		const wchar_t * json_node::name() const
		{
			if (_Name)
			{
				return _Name;
			}
			return L"";
		}

		void json_node::set_name(const wchar_t * Name)
		{
			ClearName();
			assign(_Name, Name);
		}

		JsonNodeType json_node::type() const
		{
			return _Type;
		}

		json_node * json_node::child() const
		{
			return _Child;
		}

		json_node * json_node::sibling() const
		{
			return _Sibling;
		}

		bool json_node::insert_after(json_node * sibling)
		{
			assert(sibling && sibling != this);
			if (sibling && sibling != this)
			{
				if (sibling->_Parent)
				{
					ref_storage track1;
					json_node* parent = lock<json_node>(track1, sibling->_Parent);
					if (parent)
					{
						assign(_Parent, sibling->_Parent);
						assign(this->_Sibling, sibling->_Sibling);
						assign(sibling->_Sibling, this);
						return true;
					}
				}
			}
			return false;
		}

		bool json_node::insert_child(json_node* child)
		{
			assert(child);
			if (child)
			{
				ref_storage track1;
				weak_ref* weak = create_weak(track1, this);
				assign(child->_Parent, weak);
				assign(child->_Sibling, _Child);
				assign(_Child, child);
				return true;
			}
			return false;
		}

		bool json_node::is_nil() const
		{
			return _Type == JsonNil;
		}

		bool json_node::is_array() const
		{
			return _Type == JsonArray;
		}

		bool json_node::is_object() const
		{
			return _Type == JsonObject;
		}

		bool json_node::as_bool() const
		{
			if (_Type == JsonBool)
			{
				return _Data.BoolValue;
			}
			else if (_Type == JsonNumber)
			{
				return abs(_Data.NumberValue - 0.) < SCALAR_EPSILON;
			}
			else
			{
				return false;
			}
		}

		double json_node::as_number() const
		{
			if (_Type == JsonNumber)
			{
				return _Data.NumberValue;
			}
			return 0.;
		}

		const wchar_t* json_node::as_string() const
		{
			if (_Type == JsonString)
			{
				return _Data.StringValue;
			}
			return nullptr;
		}

		size_t json_node::count() const
		{
			size_t ret = 0;
			json_node* cur = _Child;
			while (cur)
			{
				++ret;
				cur = cur->_Sibling;
			}
			return ret;
		}

		void json_node::set_nil()
		{
			ClearValue();
			_Type = JsonNil;
		}

		void json_node::set_array()
		{
			ClearValue();
			_Type = JsonArray;
		}

		void json_node::set_object()
		{
			ClearValue();
			_Type = JsonObject;
		}

		void json_node::set_value(const wchar_t * Value)
		{
			ClearValue();
			assert(Value);
			if (Value)
			{
				_Type = JsonString;
				assign(_Data.StringValue, Value);
			}
		}

		void json_node::set_value(bool Value)
		{
			ClearValue();
			_Type = JsonBool;
			_Data.BoolValue = Value;
		}

		void json_node::set_value(double Value)
		{
			ClearValue();
			_Type = JsonNumber;
			_Data.NumberValue = Value;
		}

		void * json_node::operator new(size_t sz)
		{
			return ::operator new(sz, pool);
		}

		void json_node::operator delete(void * ptr)
		{
			::operator delete(ptr, pool);
		}

		void json_node::ClearName()
		{
			if (_Name)
			{
				delete[] _Name;
				_Name = nullptr;
			}
		}

		void json_node::ClearValue()
		{
			if (_Type == JsonString)
			{
				clear(_Data.StringValue);
			}
			clear(_Child);
			_Type = JsonNil;
			memset(&_Data, 0, sizeof(_Data));
		}
	}
}